﻿using System.Net.Http;

namespace HttpClientLite;

/// <summary>
/// http管理器
/// </summary>
public class HttpManager : HttpManagerBase
{
    /// <summary>
    /// 默认实例化
    /// </summary>
    public HttpManager() : base()
    {
    }

    /// <summary>
    /// 设置地址的实例化
    /// </summary>
    /// <param name="baseAddress"></param>
    public HttpManager(string baseAddress) : base(baseAddress)
    {
    }

    /// <summary>
    /// 基于传入的HttpClient的实例化
    /// </summary>
    /// <param name="httpClient"></param>
    public HttpManager(HttpClient httpClient) : this()
    {
        this.httpClient = httpClient;
        this.baseAddress = httpClient.BaseAddress?.ToString();
    }

    /// <summary>
    /// 发送
    /// </summary>
    /// <param name="httpRequest"></param>
    /// <param name="completionOption"></param>
    /// <returns></returns>
    public override HttpResponseMessage Send(HttpRequestMessage httpRequest, HttpCompletionOption? completionOption = null)
    {
        return SendAsync(httpRequest).GetAwaiter().GetResult();
    }

    /// <summary>
    /// 异步发送
    /// </summary>
    /// <param name="httpRequest"></param>
    /// <param name="completionOption"></param>
    /// <param name="cancellationToken"></param>
    /// <returns></returns>
    public override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage httpRequest, HttpCompletionOption? completionOption = null, CancellationToken? cancellationToken = null)
    {
        HttpRequestMessage? cloneHttpRequest = null;

        HttpResponseMessage? httpResponse = null;

        try
        {
            var httpClient = GetHttpClient();

            PreSendConfiguration(httpRequest);

            if (_responseMessageHandler.Count > 0)
                cloneHttpRequest = await HttpHelper.CloneAsync(httpRequest);

            if (completionOption.HasValue && cancellationToken.HasValue)
            {
                httpResponse = await httpClient.SendAsync(httpRequest, completionOption.Value, cancellationToken.Value);
            }
            else if (completionOption.HasValue)
            {
                httpResponse = await httpClient.SendAsync(httpRequest, completionOption.Value);
            }
            else if (cancellationToken.HasValue)
            {
                httpResponse = await httpClient.SendAsync(httpRequest, cancellationToken.Value);
            }
            else
            {
                httpResponse = await httpClient.SendAsync(httpRequest);
            }

            if (_responseMessageHandler.Count > 0)
            {
                foreach (var handler in _responseMessageHandler)
                {
                    httpResponse = await handler.HandleAsync(this, httpClient, cloneHttpRequest!, httpResponse, cancellationToken);
                }
            }

            return httpResponse;
        }
        catch (Exception ex)
        {
            foreach (var handler in _httpManagerExceptionHandler)
            {
                handler.Handle(ex, httpResponse);
            }

            if (IsThrowException)
                throw;
            else
                return null!;
        }
        finally
        {
            cloneHttpRequest?.Dispose();
        }
    }

    private void PreSendConfiguration(HttpRequestMessage httpRequest)
    {
        foreach (var configuration in _httpManagerConfiguration)
        {
            configuration.Configure(this);
        }

        var httpClient = GetHttpClient();

        foreach (var configuration in _httpClientConfiguration)
        {
            configuration.Configure(httpClient);
        }

        foreach (var configuration in _requestMessageConfiguration)
        {
            configuration.Configure(httpRequest);
        }
    }
}